package com.xxll.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.xxll.domain.SysMenu;
import com.xxll.feign.JwtToken;
import com.xxll.feign.OAuth2FeignClient;
import com.xxll.model.LoginResult;
import com.xxll.service.SysLoginService;
import com.xxll.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <h2>登录接口</h2>
 *
 * @Author Zeny
 */
@Slf4j
@Service
public class SysLoginServiceImpl implements SysLoginService {

    @Autowired
    private OAuth2FeignClient oAuth2FeignClient;

    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
    private String basicToken ;

    /**
     * <h2>登录的实现</h2>
     * @param username 用户名
     * @param password 密码
     **/
    @Override
    public LoginResult login(String username, String password) {
        log.info("用户【{}】开始登录", username);
        // 1、获取token 通过远程调用 authorization-server授权服务器器获取
        ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", username, password, "admin_type", basicToken);
        if (tokenResponseEntity.getStatusCode() != HttpStatus.OK) {
            throw new ApiException(ApiErrorCode.FAILED) ;
        }
        JwtToken jwtToken = tokenResponseEntity.getBody();
        log.info("后台用户:{}, 远程调用授权服务器成功,获取的token:{}",username, JSON.toJSONString(jwtToken,true));
        String token = jwtToken.getAccessToken();
        // 2、查询该用户的菜单
        // 2.1、token解析出数据（字符串形式）
        Jwt jwt = JwtHelper.decode(token);
        String jwtJsonStr = jwt.getClaims();
        // 2.2 用户数据str转json对象
        JSONObject jwtJson = JSON.parseObject(jwtJsonStr);
        // 2.3 获取用户id，因为授权服务器登陆后使用【用户id】代替【用户名】
        Long userId = Long.valueOf(jwtJson.getString("user_name"));
        // 2.4 jwt中没有菜单数据，所有只能到数据库中查询
        List<SysMenu> menus = sysMenuService.getMemusByUserId(userId);
        // 3、获取该用户的权限数据， 从jwt中获取即可
        JSONArray authoritiesJsonArray  = jwtJson.getJSONArray("authorities");
        // 3.1、组装我们的权限数据
        List<SimpleGrantedAuthority> authorities = authoritiesJsonArray.stream()
                .map(authoritiesJson -> new SimpleGrantedAuthority(authoritiesJson.toString()))
                .collect(Collectors.toList());

        //将token 存储redis里面， 配置网关做jwt验证的操作
        redisTemplate.opsForValue().set(token, "", jwtToken.getExpiresIn(), TimeUnit.SECONDS);
        return new LoginResult(jwtToken.getTokenType() + " " +token, menus, authorities);
//        return new LoginResult(token, menus, authorities);
    }
}
